package org.dreamwork.network.gateway;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.dreamwork.util.IOUtil;

import javax.net.ssl.*;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RemoteGateway {
    private static final X509TrustManager manager = new X509TrustManager () {

        @Override
        public void checkClientTrusted (X509Certificate[] x509Certificates, String s) {

        }

        @Override
        public void checkServerTrusted (X509Certificate[] x509Certificates, String s) {

        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    };
    public static void main (String[] args) throws InterruptedException, IOException, NoSuchAlgorithmException, KeyManagementException {
        URL url = new URL ("https://devel.hothink.net.cn");
        HttpsURLConnection conn = (HttpsURLConnection) url.openConnection ();
        SSLContext ctx = SSLContext.getInstance("TLS");
        ctx.init(null, new TrustManager[] { manager }, null);
        SSLSocketFactory ssf = ctx.getSocketFactory ();
        conn.setSSLSocketFactory (ssf);
        conn.setDoInput (true);
        try (InputStream in = conn.getInputStream ()) {
            IOUtil.dump (in, System.out);
        } finally {
            conn.disconnect ();
        }
//        new RemoteGateway ().start ();
    }

    private final int port;

    public RemoteGateway () {
        this (1080);
    }

    public RemoteGateway (int port) { this.port = port; }

    public void start () throws InterruptedException {
        NioEventLoopGroup group = new NioEventLoopGroup ();
        try {
            ServerBootstrap server = new ServerBootstrap ();
            server.group (group)
                    .channel (NioServerSocketChannel.class)
                    .localAddress (port)
                    .childHandler (new ChannelInitializer<SocketChannel> () {
                        @Override
                        protected void initChannel (SocketChannel channel) throws Exception {
                            channel.pipeline ().addLast (new EchoServerHandler ());
                        }
                    });
            ChannelFuture future = server.bind().sync();
            future.channel ().closeFuture ().sync ();
        } finally {
            group.shutdownGracefully ().sync ();
        }
    }

    private static final class EchoServerHandler extends ChannelInboundHandlerAdapter {
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) {
            ByteBuf in = (ByteBuf) msg;
            String content = in.toString (StandardCharsets.UTF_8);
            System.out.println("Server received: " + content); //2
//            ctx.write(in); //3
            System.out.println ("================================");

            Pattern P = Pattern.compile ("^(GET|POST|PUT|DELETE)\\s+(.*?)\\s+HTTP/1\\.\\d\\s*$");

            int pos = content.indexOf ('\n');
            String firstLine = content.substring (0, pos).trim ();
            Matcher m = P.matcher (firstLine);
            if (m.matches ()) {
                String server = m.group (1);
                System.out.println (server);


            }
        }
        @Override
        public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
            ctx.writeAndFlush(Unpooled.EMPTY_BUFFER);
//                    .addListener(ChannelFutureListener.CLOSE);
        }
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx,
                                    Throwable cause) {
            cause.printStackTrace();
            ctx.close();
        }
    }
}
